/*************************************************************
*
* DS_PTR_LIST.HPP
* 
*************************************************************/

namespace ds {

/***************************************************************
* PTR_LIST::Insert(T &val, ITERATOR where)
*
***************************************************************/
template <typename T, typename NODE_AP> 
typename PTR_LIST<T,NODE_AP>::ITERATOR 
PTR_LIST<T,NODE_AP>::Insert (T *val, ITERATOR where)
{
   if (!pHead) {
      NODE_AP::SetPrev(val, 0);
      NODE_AP::SetNext(val, 0);

      // it's first element
      pTail = pHead = val;
   } else {
      T *pWhere = where.operator->();

      NODE_AP::SetNext(val, NODE_AP::Next(pWhere));
      NODE_AP::SetPrev(val, pWhere);

      NODE_AP::SetNext(pWhere, val);

      if (!NODE_AP::Next(val)) {
         pTail = val;
      } else {
         NODE_AP::SetPrev(NODE_AP::Next(val), val);
      }
   }

   length++;

   return ITERATOR(val);
}

/***************************************************************
* PTR_LIST::PushFront (T &val, ITERATOR where)
*
***************************************************************/
template <typename T, typename NODE_AP> 
typename PTR_LIST<T,NODE_AP>::ITERATOR 
PTR_LIST<T,NODE_AP>::PushFront (T *val)
{
   if (!pHead) {
      NODE_AP::SetPrev(val, 0);
      NODE_AP::SetNext(val, 0);

      // it's first element
      pTail = pHead = val;
   } else {
      NODE_AP::SetPrev(val, 0);
      NODE_AP::SetNext(val, pHead);

      NODE_AP::SetPrev(pHead, val);

      pHead = val;
   }

   length++;

   return ITERATOR(val);
}

/***************************************************************
* PTR_LIST::Erase (ITERATOR where)
*
***************************************************************/
template <typename T, typename NODE_AP> 
T* PTR_LIST<T, NODE_AP>::Erase (ITERATOR where)
{
   T *pItem = where.operator->();

   T *pPrev = NODE_AP::Prev(pItem);
   T *pNext = NODE_AP::Next(pItem);

   if (!pPrev) {
      pHead = pNext;
      if (pHead) {
         NODE_AP::SetPrev(pHead, 0);
      } 
   } else {
      NODE_AP::SetNext(pPrev, pNext);
   } 

   if (!pNext) {
      pTail = pPrev;
      if (pTail) {
         NODE_AP::SetNext(pTail, 0);
      }      
   } else {
      NODE_AP::SetPrev(pNext, pPrev);
   }

   NODE_AP::SetPrev(pItem, 0);
   NODE_AP::SetNext(pItem, 0);

   length--;

   return pItem;
}

/***************************************************************
* void PTR_LIST<T, NODE_AP>::Clear ()
*
***************************************************************/
template <typename T, typename NODE_AP>
void PTR_LIST<T, NODE_AP>::Clear (void)
{
   while (pHead != NULL) {
      T* pCur = pHead;
      pHead = NODE_AP::Next(pHead);
      NODE_AP::SetPrev(pCur, 0);
      NODE_AP::SetNext(pCur, 0);
   }

   pTail  = NULL;
   length = 0;

   return ;
}

} // namespace ds

//
// End-of-file DS_PTR_LIST.HPP
//

